package org.zergle.utils;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;

/**
 * 属性文件加载器
 * 
 * @author Johnson.Lee
 * 
 */
public class PropertiesLoader {
	private static final Iterator<String> EMPTY_ITERATOR = new EmptyIterator();
	private final Properties prop = new Properties();

	/**
	 * 根据字节输入流构造 <code>PropertiesLoader</code>
	 * 
	 * @param is
	 *            字节输入流
	 * @throws IOException
	 */
	public PropertiesLoader(InputStream is) throws IOException {
		this(new InputStreamReader(is));
	}

	/**
	 * 根据字符输入流构造 <code>PropertiesLoader</code>
	 * 
	 * @param reader
	 *            字符输入流
	 * @throws IOException
	 */
	public PropertiesLoader(Reader reader) throws IOException {
		this.prop.load(reader);
	}

	/**
	 * 根据资源名称构造 <code>PropertiesLoader</code>
	 * 
	 * @param name
	 *            资源名称
	 * @throws IOException
	 */
	public PropertiesLoader(String name) throws IOException {
		this(PropertiesLoader.class.getResourceAsStream(name));
	}

	/**
	 * 查找指定键对应的值
	 * 
	 * @param key
	 *            键
	 * @return 指定键对应的值
	 */
	public String lookup(String key) {
		return this.prop.getProperty(key);
	}

	/**
	 * 为指定键设置值
	 * 
	 * @param key
	 *            键
	 * @param value
	 *            值
	 */
	public void set(String key, String value) {
		this.prop.setProperty(key, value);
	}

	/**
	 * 保存配置到指定的输出流中
	 * 
	 * @param os
	 *            字节输出流
	 * @throws IOException
	 */
	public void save(OutputStream os) throws IOException {
		this.prop.store(os, "");
	}

	/**
	 * 查找指定键对应的值，如果不存在则返回默认值
	 * 
	 * @param key
	 *            键
	 * @param defaultValue
	 *            默认值
	 * @return 指定键对应的值
	 */
	public String lookup(String key, String defaultValue) {
		return this.prop.getProperty(key, defaultValue);
	}

	/**
	 * 返回所有键名称的迭代器
	 * 
	 * @return 所有键名称的迭代器
	 */
	public Iterator<String> propertyNames() {
		Set<?> keys = this.prop.keySet();
		if (keys != null) {
			final Iterator<?> keyIt = keys.iterator();
			return new Iterator<String>() {

				public boolean hasNext() {
					return keyIt.hasNext();
				}

				public String next() {
					return String.valueOf(keyIt.next());
				}

				public void remove() {
				}
				
			};
		}
		return EMPTY_ITERATOR;
	}

	/**
	 * 返回指定键对应的整型值。
	 * 
	 * @param key
	 *            键
	 * @return 指定键对应的整型值
	 * @throws NumberFormatException
	 *             如果指定键对应的值为null或其字符串形式不是整数形式，则抛出此异常
	 */
	public int getInt(String key) throws NumberFormatException {
		return Integer.parseInt(this.lookup(key, "0"));
	}

	/**
	 * 返回指定键对应的浮点值。
	 * 
	 * @param key
	 *            键
	 * @return 指定键对应的浮点值
	 * @throws NumberFormatException
	 *             如果指定键对应的值为null或其字符串形式不是小数形式，则抛出此异常
	 */
	public float getFloat(String key) throws NumberFormatException {
		return Float.parseFloat(this.lookup(key, "0"));
	}

	/**
	 * 返回指定键对应的布尔值。如果指定键对应的值为null或其字符串形式不为true(忽略大小写)，则返回false
	 * 
	 * @param key
	 *            键
	 * @return 指定键对应的布尔值
	 */
	public boolean getBoolean(String key) {
		return new Boolean(this.lookup(key, "false"));
	}

	private static final class EmptyIterator implements Iterator<String> {

		public boolean hasNext() {
			return false;
		}

		public String next() {
			return null;
		}

		public void remove() {
			throw new UnsupportedOperationException();
		}
	}

}